//==========================================================================
// Copyright (c) 2000-2008,  Elastos, Inc.  All Rights Reserved.
//==========================================================================
//==========================================================================
// Copyright (c) 2000-2004,  Elastos, Inc.  All Rights Reserved.
//**author:hanxu
//**y/m/d:2005/5/26
//==========================================================================

#ifndef __ELASTOS_VGA_H__
#define __ELASTOS_VGA_H__

#define KNOWN_VGAMODES      1
#define VGATXTMODE          0
#define VGAGDIMODE          1

#define SIZE_SR00_SR04      (0x04 - 0x00 + 1)
#define SIZE_SR10_SR24      (0x24 - 0x10 + 1)
#define SIZE_SR30_SR75      (0x75 - 0x30 + 1)
#define SIZE_SR80_SR93      (0x93 - 0x80 + 1)
#define SIZE_SRA0_SRAF      (0xAF - 0xA0 + 1)
#define SIZE_GR00_GR08      (0x08 - 0x00 + 1)
#define SIZE_AR00_AR14      (0x14 - 0x00 + 1)
#define SIZE_CR00_CR18      (0x18 - 0x00 + 1)
#define SIZE_CR30_CR4D      (0x4D - 0x30 + 1)
#define SIZE_CR90_CRA7      (0xA7 - 0x90 + 1)
#define SIZE_VPR            (0x6C + 1)
#define SIZE_DPR            (0x44 + 1)

struct VgaRegs
{
    uint16_t    chipID;
    uint8_t     *puLFB;
    uint8_t     *puMMIO;
    uint8_t     *puDPR;
    uint8_t     *puVPR;
    uint8_t     *puCPR;
};

typedef struct vgaInfo
{
    VgaRegs  vgaregs;
    uint32_t frameBuf;
    uint32_t ioBuf;
} vgaInfo;
typedef struct VGAModeInit
{
    uint32_t     uSizeX;
    uint32_t     uSizeY;
    uint32_t     uBpp;
    uint32_t     uHz;
    uint8_t Init_MISC;
    uint8_t Init_SR00_SR04[SIZE_SR00_SR04];
    uint8_t Init_SR10_SR24[SIZE_SR10_SR24];
    uint8_t Init_SR30_SR75[SIZE_SR30_SR75];
    uint8_t Init_SR80_SR93[SIZE_SR80_SR93];
    uint8_t Init_SRA0_SRAF[SIZE_SRA0_SRAF];
    uint8_t Init_GR00_GR08[SIZE_GR00_GR08];
    uint8_t Init_AR00_AR14[SIZE_AR00_AR14];
    uint8_t Init_CR00_CR18[SIZE_CR00_CR18];
    uint8_t Init_CR30_CR4D[SIZE_CR30_CR4D];
    uint8_t Init_CR90_CRA7[SIZE_CR90_CRA7];
} VGAModeInit;

typedef struct vgaInitParam
{
    uint32_t ScrWidth;
    uint32_t ScrHeight;
    uint32_t Bpp;
    uint32_t Hz;
    uint32_t CursorLocation;
    uint32_t TxtCursorLocation;
    uint32_t CharWidth;
    uint32_t CharHeight;
    uint16_t DrawColor;
} vgaInitParam;

class Video : public CDeviceDriver
{
public:
    CARAPI Read(
        /* [in] */ UInt64 u64Offset,
        /* [in] */ UInt32 bytesToRead,
        /* [out] */ MemoryBuf * pBuffer,
        /* [out] */ IEvent * * ppCompletionEvent);

    CARAPI Write(
        /* [in] */ UInt64 u64Offset,
        /* [in] */ const MemoryBuf & buffer,
        /* [out] */ UInt32 * pBytesWritten,
        /* [out] */ IEvent * * ppCompletionEvent);

    CARAPI Control(
        /* [in] */ Handle32 nControlCode,
        /* [in] */ const MemoryBuf & inBuffer,
        /* [out] */ MemoryBuf * pOutBuffer,
        /* [out] */ IEvent * * ppCompletionEvent);

    CARAPI WritePixel(
        /* [in] */ UInt64 u64Offset,
        /* [in] */ const MemoryBuf & buffer,
        /* [out] */ UInt32 * pBytesWritten,
        /* [out] */ IEvent * * ppCompletionEvent);

    ECode m_vga_init(vgaInitParam *pvParameter, vgaInfo *pInfo);

    virtual void Dispose() {}

    Video()
    {
        m_uScrWidth = 800;
        m_uScrHeight = 600;
        m_uScrBpp = 16;
        m_uScrHz = 60;

        m_uCursorLocation = 0;
        m_uTxtCursorLocation = 0;

        m_uCharWidth = 8;
        m_uCharHeight = 16;
        m_u16DrawColor = 0xffff;
        m_uScrTxtCols = m_uScrWidth / m_uCharWidth;
        m_uScrTxtRows = m_uScrHeight / m_uCharHeight;
        m_bGDIMODE = false;
    }

private:

public:

    uint32_t            m_uCursorLocation;
    uint32_t            m_uTxtCursorLocation;

    // screen initialise parameter:
    uint32_t            m_uScrWidth;
    uint32_t            m_uScrHeight;
    uint32_t            m_uScrBpp;
    uint32_t            m_uScrHz;

    // for text mode
    uint32_t            m_uScrTxtCols;
    uint32_t            m_uScrTxtRows;
    uint32_t            m_uCharWidth;
    uint32_t            m_uCharHeight;
    uint16_t            m_u16DrawColor;
//    uint8_t             m_u8TextFont;

    VgaRegs          m_vga_regs;

    uint32_t         m_uVirtAddr; // mapped vga virtual address for
                                  // user-mode calls
    uint32_t         m_uFrameBufBase; // vga frame buffer physical base address
    uint32_t         m_uIoBufBase;    // vga IO buffer physical base address

    uint32_t         m_uVgaMemSize; // probed vga memory size
    bool             m_bGDIMODE;
};

EXTERN IDeviceDriver * CDECL CreateVGA(uint_t uDeviceNo, void *pvParameter);
EXTERN void DrawChar(char c, uint32_t buffer, uint16_t draw_color);

#endif // __ELASTOS_VGA_H__
